/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.core.json.converter.json.converter.factory;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Strings;
import com.je.bpm.core.model.config.task.assignment.*;

import java.util.ArrayList;
import java.util.List;

import static com.je.bpm.core.json.converter.constants.StencilConstants.*;

/**
 * 人员工厂
 */
public class AssignmentConfigFactory {

    private static BasicAssignmentConfigImpl newBasicAssignmentConfigImplByType(String type) {
        DepartmentAssignmentConfigImpl departmentAssignmentConfig = new DepartmentAssignmentConfigImpl();
        RoleAssignmentConfigImpl roleAssignmentConfig = new RoleAssignmentConfigImpl();
        PositionAssignmentConfigImpl positionAssignmentConfig = new PositionAssignmentConfigImpl();
        BusinessSqlAssignmentConfigImpl businessSqlAssignmentConfig = new BusinessSqlAssignmentConfigImpl();
        CustomAssignmentConfigImpl customAssignmentConfig = new CustomAssignmentConfigImpl();
        FormFieldAssignmentConfigImpl formFieldAssignmentConfig = new FormFieldAssignmentConfigImpl();
        OrgTreeAssignmentConfigImpl orgTreeAssignmentConfig = new OrgTreeAssignmentConfigImpl();
        SpecialAssignmentConfigImpl specialAssignmentConfig = new SpecialAssignmentConfigImpl();
        UserAssignmentConfigImpl userAssignmentConfig = new UserAssignmentConfigImpl();
        //部门
        if (type.equals(departmentAssignmentConfig.getConfigType())) {
            return new DepartmentAssignmentConfigImpl();
        }

        //角色
        if (type.equals(roleAssignmentConfig.getConfigType())) {
            return new RoleAssignmentConfigImpl();
        }

        //岗位
        if (type.equals(positionAssignmentConfig.getConfigType())) {
            return new PositionAssignmentConfigImpl();
        }

        //人员
        if (type.equals(userAssignmentConfig.getConfigType())) {
            return new UserAssignmentConfigImpl();
        }

        //sql
        if (type.equals(businessSqlAssignmentConfig.getConfigType())) {
            return new BusinessSqlAssignmentConfigImpl();
        }

        //自定义
        if (type.equals(customAssignmentConfig.getConfigType())) {
            return new CustomAssignmentConfigImpl();
        }

        //表单
        if (type.equals(formFieldAssignmentConfig.getConfigType())) {
            return new FormFieldAssignmentConfigImpl();
        }

        //组织架构
        if (type.equals(orgTreeAssignmentConfig.getConfigType())) {
            return new OrgTreeAssignmentConfigImpl();
        }

        //特殊处理
        if (type.equals(specialAssignmentConfig.getConfigType())) {
            return new SpecialAssignmentConfigImpl();
        }
        return null;
    }


    public static BasicAssignmentConfigImpl getAssignmentConfigByJson(String type, JsonNode itemNode) {
        if (type == null || type.isEmpty()) {
            return null;
        }

        BasicAssignmentConfigImpl assignmentConfig = newBasicAssignmentConfigImplByType(type);
        //路径
        assignmentConfig.setEntryPath(getValueAsString(PROPERTY_ASSIGNMENT_ENTRY_PATH_CONFIG, itemNode));

        //角色、部门、岗位
        if (assignmentConfig instanceof PositionAssignmentConfigImpl) {
            PositionAssignmentConfigImpl positionAssignmentConfig = (PositionAssignmentConfigImpl) assignmentConfig;
            positionAssignmentConfig.addResource(getAssigneeResource(itemNode));
            positionAssignmentConfig.setPermission(getAssignmentPermission(itemNode));
            return positionAssignmentConfig;
        }

        if (assignmentConfig instanceof DepartmentAssignmentConfigImpl) {
            DepartmentAssignmentConfigImpl departmentAssignmentConfig = (DepartmentAssignmentConfigImpl) assignmentConfig;
            departmentAssignmentConfig.addResource(getAssigneeResource(itemNode));
            departmentAssignmentConfig.setPermission(getAssignmentPermission(itemNode));
            return departmentAssignmentConfig;
        }

        if (assignmentConfig instanceof RoleAssignmentConfigImpl) {
            RoleAssignmentConfigImpl roleAssignmentConfig = (RoleAssignmentConfigImpl) assignmentConfig;
            roleAssignmentConfig.addResource(getAssigneeResource(itemNode));
            roleAssignmentConfig.setPermission(getAssignmentPermission(itemNode));
            return roleAssignmentConfig;
        }

        //人员
        if (assignmentConfig instanceof UserAssignmentConfigImpl) {
            UserAssignmentConfigImpl userAssignmentConfig = (UserAssignmentConfigImpl) assignmentConfig;
            userAssignmentConfig.addResource(getAssigneeResource(itemNode));
            return userAssignmentConfig;
        }

        //表单字段
        if (assignmentConfig instanceof FormFieldAssignmentConfigImpl) {
            FormFieldAssignmentConfigImpl formFieldAssignmentConfig = (FormFieldAssignmentConfigImpl) assignmentConfig;
            formFieldAssignmentConfig.addResource(getAssigneeResource(itemNode));
            return formFieldAssignmentConfig;
        }

        //组织架构
        if (assignmentConfig instanceof OrgTreeAssignmentConfigImpl) {
            OrgTreeAssignmentConfigImpl orgTreeAssignmentConfig = (OrgTreeAssignmentConfigImpl) assignmentConfig;
            JsonNode config = itemNode.get(UNIVERSAL_CONFIG);
            orgTreeAssignmentConfig.setEnable(true);
            return orgTreeAssignmentConfig;
        }

        //自定义service
        if (assignmentConfig instanceof CustomAssignmentConfigImpl) {
            CustomAssignmentConfigImpl customAssignmentConfig = (CustomAssignmentConfigImpl) assignmentConfig;
            customAssignmentConfig.setServiceName(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_SERVICENAME, itemNode));
            customAssignmentConfig.setMethodName(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_METHODNAME, itemNode));
            return customAssignmentConfig;
        }

        //特殊处理
        if (assignmentConfig instanceof SpecialAssignmentConfigImpl) {
            SpecialAssignmentConfigImpl specialAssignmentConfig = (SpecialAssignmentConfigImpl) assignmentConfig;
            List<SpecialAssignmentConfigImpl.SpectialTypeEnum> list = specialAssignmentConfig.getSpecialType();
            String resources = getValueAsString(UNIVERSAL_RESOURCE_CODE, itemNode);
            if (!Strings.isNullOrEmpty(resources)) {
                String[] fields = resources.split(",");
                for (String name : fields) {
                    list.add(SpecialAssignmentConfigImpl.SpectialTypeEnum.getType(name));
                }
            }
            specialAssignmentConfig.setSpecialType(list);
            return specialAssignmentConfig;
        }

        //sql
        if (assignmentConfig instanceof BusinessSqlAssignmentConfigImpl) {
            BusinessSqlAssignmentConfigImpl businessSqlAssignmentConfig = (BusinessSqlAssignmentConfigImpl) assignmentConfig;
            businessSqlAssignmentConfig.setSql(getValueAsString(UNIVERSAL_SQL, itemNode));
            return businessSqlAssignmentConfig;
        }

        return null;
    }

    private static List<AssigneeResource> getAssigneeResource(JsonNode itemNode) {
        List<AssigneeResource> resource = new ArrayList<>();
        String ids = getValueAsString(UNIVERSAL_RESOURCE_ID, itemNode);
        String codes = getValueAsString(UNIVERSAL_RESOURCE_CODE, itemNode);
        String names = getValueAsString(UNIVERSAL_RESOURCE_NAME, itemNode);

        if (Strings.isNullOrEmpty(ids)) {
            return resource;
        }
        String[] idsArray = ids.split(",");
        String[] codesArray = codes.split(",");
        String[] namesArray = names.split(",");
        AssigneeResource assigneeResource;
        for (int i = 0; i < idsArray.length; i++) {
            String id = idsArray[i];
            String code = codesArray[i];
            String name = namesArray[i];
            assigneeResource = new AssigneeResource(name, id, code);
            resource.add(assigneeResource);
        }
        return resource;
    }

    private static AssignmentPermission getAssignmentPermission(JsonNode itemNode) {
        AssignmentPermission permission = new AssignmentPermission();
        JsonNode permissionNode = itemNode.get(PROPERTY_ASSIGNMENT_PERMISSION_CONFIG);
        permission.setCompany(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY, permissionNode));
        permission.setCompanySupervision(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY_SUPERVISION, permissionNode));
        permission.setDept(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_DEPT, permissionNode));
        permission.setDeptAll(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_ALL, permissionNode));
        permission.setDirectLeader(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_DIRECT_LEADER, permissionNode));
        permission.setDeptLeader(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_LEADER, permissionNode));
        permission.setSupervisionLeader(getValueAsBoolean(PROPERTY_ASSIGNMENT_PERMISSION_SUPERVISION_LEADER, permissionNode));
        permission.setSql(getValueAsString(UNIVERSAL_SQL, permissionNode));
        permission.setSqlRemarks(getValueAsString(PROPERTY_ASSIGNMENT_PERMISSION_SQL_REMARKS, permissionNode));
        return permission;
    }

    protected static String getValueAsString(String name, JsonNode objectNode) {
        if (objectNode == null) {
            return "";
        }
        String propertyValue = null;
        JsonNode propertyNode = objectNode.get(name);
        if (propertyNode != null && !propertyNode.isNull()) {
            propertyValue = propertyNode.asText();
        }
        return propertyValue;
    }

    protected static boolean getValueAsBoolean(String name, JsonNode objectNode) {
        boolean propertyValue = false;
        if (objectNode == null) {
            return false;
        }
        JsonNode propertyNode = objectNode.get(name);
        if (propertyNode != null && !propertyNode.isNull()) {
            propertyValue = propertyNode.asBoolean();
        }
        if (propertyValue == false) {
            if (objectNode.get(name) == null) {
                return false;
            }
            if (!Strings.isNullOrEmpty(objectNode.get(name).asText()) && objectNode.get(name).asText().equals("1")) {
                propertyValue = true;
            }
        }
        return propertyValue;
    }

}
